using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace SCG.General
{
    //A Panel control that can resize child controls proportionately as it is resized
    public partial class ElasticPanel : Panel
    {
        //Internal class uses to store original size and position of child controls
        class ControlState
        {
            internal int _width;
            internal int _height;
            internal int _left;
            internal int _top;          
        }

        //Private members
        private bool _stretchHorizontal = true;
        private bool _stretchVertical = true;
        private Dictionary<Control, ControlState> _controlStates = new Dictionary<Control, ControlState>();
        private bool _firstResize = true;
        private int _originalWidth;
        private int _originalHeight;

        //Constructors
        public ElasticPanel()
        {
            InitializeComponent();
        }
        public ElasticPanel(IContainer container)
        {
            container.Add(this);
            InitializeComponent();
        }

        //Public properties
        public bool StretchHorizontal
        {
            get
            {
                return _stretchHorizontal;
            }
            set
            {
                _stretchHorizontal = value;
            }
        }
        public bool StretchVertical
        {
            get
            {
                return _stretchVertical;
            }
            set
            {
                _stretchVertical = value;
            }
        }     
      
        //force a resize
        public void ForceResize()
        {
            OnResize(EventArgs.Empty);
        }

        //Intercept resize event to stretch child controls contained
        protected override void OnResize(EventArgs eventargs)
        {
            ControlState cs;
            base.OnResize(eventargs);
            //Do not process during design-mode
            if (DesignMode)
            {
                return;
            }
            //First resize occurs when panel first created, use this opportunity to store
            //original size of the panel
            if (_firstResize)
            {
                _firstResize = false;
                _originalWidth = Width;
                _originalHeight = Height;
                return;
            }
            //Process each cild control contained in panel
            foreach (Control c in Controls)
            {
                //First resize event will stash original position and size in ControlState object
                if (!_controlStates.ContainsKey(c))
                {
                    cs = new ControlState();
                    cs._width = c.Width;
                    cs._height = c.Height;
                    cs._left = c.Left;
                    cs._top = c.Top;               
                    _controlStates.Add(c, cs);
                }
                //Look up the control's original location and size               
                cs = _controlStates[c];
                //Get multiples of the panel's original size to current size
                float xMult = (float)Width / (float)_originalWidth;
                float yMult = (float)Height / (float)_originalHeight;
                //Perform horizontal resizing of control
                if (StretchHorizontal)
                {
                    c.Left = (int)(cs._left * xMult);
                    c.Width = (int)(cs._width * xMult);
                }
                //Perform vertical resizing of control
                if (StretchVertical)
                {
                    c.Top = (int)(cs._top * yMult);
                    c.Height = (int)(cs._height * yMult);
                }
            }            
        }
    }
}
